package core.proto.rightwindow;

//import java.applet.*; 
import java.applet.AudioClip;
import java.awt.*; 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.*; 
import java.net.*; 
import java.util.*; 

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.Timer;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import com.oreilly.servlet.HttpMessage; 

import core.proto.AllComponents;
import core.proto.InfoViz;
import core.proto.Util;
import core.util.logging.UserLogWriter;
import core.util.logging.constants.Action;
import core.util.logging.constants.Location;

public class HttpChatPanel extends JPanel implements Runnable, MessageTypes, MouseListener, KeyListener {
	final static boolean shouldFill = true;
	final static boolean shouldWeightX = true;
	
	static JTextPane chatDisplayArea;
	StyledDocument SD;
	JTextField chatEntryArea; 
	JButton sendButton;
	Thread chatThread; 
	String user = InfoViz.UserID; 
	JScrollPane cArea;
	static int endPoint = 0;
	static HttpChatPanel instance;
	boolean mouseInside = false;
	
	private HashSet<Integer> activeKeys = new HashSet<Integer>();
	
	private Timer timer = new Timer(0, null);

	public HttpChatPanel() { 
		// Set up the user interface... 
		// On top, a large TextArea showing what everyone's saying. 
		// Underneath, a labeled TextField to accept this user's input.

		instance = this;
		
		addMouseListener(this);
		addKeyListener(this);
		
		JLabel chatLabel = new JLabel("   Chat:");
		TextHandler handler = new TextHandler();

		chatEntryArea = new JTextField(17);
		chatEntryArea.addKeyListener(handler);
		chatEntryArea.addKeyListener(new KeyListener(){

			@Override
			public void keyPressed(KeyEvent e) {
				activeKeys.add(e.getKeyCode());
				
				
				 if(activeKeys.contains(KeyEvent.VK_CONTROL) && activeKeys.contains(KeyEvent.VK_C)){
					 UserLogWriter.log2(Action.KEYCOPY, Location.Chat.toString(), "Chat Text Field", "null", "null", "null", "null", "null");
					}
				 else{
					timer.stop();
					
					int delay = 500; //milliseconds
					  ActionListener taskPerformer = new ActionListener() {
					      public void actionPerformed(ActionEvent evt) {
					    	  UserLogWriter.log2(Action.KEYTYPE, Location.Chat.toString(), "Chat Text Field", "null", "null", "null", "null", "null");
					      }
					  };
					 timer = new Timer(delay, taskPerformer);
					 timer.setRepeats(false);
					 timer.start();
				 }
				 
				
					if(activeKeys.contains(KeyEvent.VK_CONTROL) && activeKeys.contains(KeyEvent.VK_V)){
						UserLogWriter.log2(Action.KEYPASTE, Location.Chat.toString(), "Chat Text Field", "null", "null", "null", "null", "null");
					}
			}

			@Override
			public void keyReleased(KeyEvent e) {
				activeKeys.remove(e.getKeyCode());
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}
			
		});
		chatEntryArea.addMouseListener(new MouseListener(){

			@Override
			public void mouseClicked(MouseEvent arg0) {
				UserLogWriter.log2(Action.CLICK, Location.Chat.toString(), "Chat Text Field", "null", "null", "null", "null", "null");
			}

			@Override
			public void mouseEntered(MouseEvent arg0) {
			}

			@Override
			public void mouseExited(MouseEvent arg0) {
			}

			@Override
			public void mousePressed(MouseEvent arg0) {
			}

			@Override
			public void mouseReleased(MouseEvent arg0) {
			}
			
		});
		
		sendButton = new JButton("Send");
		sendButton.setSize((int) (sendButton.getWidth() * 0.2), (int) (sendButton.getHeight() * 0.2));
		sendButton.addActionListener(new ActionListener() {
		    @Override
		    public void actionPerformed(ActionEvent evt) {
		    	String text = chatEntryArea.getText();
		    	if(!text.equals("")){
					chatEntryArea.setText("");
					broadcastMessage(text);
		    	}
		    }
		});
		sendButton.addMouseListener(new MouseListener(){

			@Override
			public void mouseClicked(MouseEvent arg0) {
				UserLogWriter.log2(Action.CLICK, Location.Chat.toString(), "Chat Text Field Send Button", "null", "null", "null", "null", "null");
			}

			@Override
			public void mouseEntered(MouseEvent arg0) {
			}

			@Override
			public void mouseExited(MouseEvent arg0) {
			}

			@Override
			public void mousePressed(MouseEvent arg0) {
			}

			@Override
			public void mouseReleased(MouseEvent arg0) {
			}
			
		});
		
		

		chatDisplayArea = new JTextPane();
		chatDisplayArea.setEditable(false);
		chatDisplayArea.setDragEnabled(true);
		chatDisplayArea.setVisible(true);

		
		
		//chatDisplayArea.setSize(chatDisplayArea.getWidth(), chatDisplayArea.getHeight() + 100);

		cArea = new JScrollPane(chatDisplayArea);
		cArea.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		cArea.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		cArea.setPreferredSize(new Dimension(250,270));
		
		// Use a grid bag layout for our chat panel. 
		GridBagLayout gridBag = new GridBagLayout();
		this.setLayout(gridBag);
		GridBagConstraints gridCons = new GridBagConstraints();

		gridCons.gridx = 0;
		gridCons.gridy = 0;
		this.add(chatLabel, gridCons);
		
		gridCons.gridwidth = 3;

		gridCons.gridx = 0;
		gridCons.gridy = 1;
		this.add(cArea, gridCons);
		
		gridCons.ipadx = 0;
		gridCons.gridwidth = 2;
		gridCons.insets = new Insets(10,0,0,0);  //top padding
		gridCons.gridx = 0;
		gridCons.gridy = 2;
		this.add(chatEntryArea, gridCons);
		
		gridCons.gridwidth = 1;
		gridCons.gridy = 2;
		gridCons.gridx = 2;
		this.add(sendButton, gridCons);

		if (user == null) user = "Anonymous";
		this.start();
		
	} 
	
	public JTextPane getChatDisplayArea(){
		return chatDisplayArea;
	}
	
	public JTextField getChatEntryArea(){
		return chatEntryArea;
	}

	public void start() { 
		chatThread = new Thread(this); 
		chatThread.start(); 
		
		new Thread(
	            new Runnable() {
	                public void run() {
	                	while(true){
	                		Document doc = chatDisplayArea.getDocument();
	                		
	                		SimpleAttributeSet keyWord = new SimpleAttributeSet();
	                		
	                		StyleConstants.setForeground(keyWord, Color.red);
	                		
	                		String notification = getNextNotification();
	                		
	                		int x;
	            			chatDisplayArea.selectAll();
	            			 x = chatDisplayArea.getSelectionEnd();
	            			 chatDisplayArea.select(x,x);
	            			repaint();
	            			
	            			System.out.println("ENDPOINT : " + endPoint);
	            			
	            			JOptionPane.showMessageDialog(null, notification);
	            			
	                	}
	                }
	            }).start();
		
		new Thread(
	            new Runnable() {
	                public void run() {
	                	while(true){
	                		Document doc = chatDisplayArea.getDocument();
	                		
	                		SimpleAttributeSet keyWord = new SimpleAttributeSet();
	                		
	                		StyleConstants.setForeground(keyWord, Color.red);
	                		
	                		String notification = getNextSystemMessage();

	                		
	                		notification = "\n" + notification + "\n\n";
	                		
	                		int x;
	            			chatDisplayArea.selectAll();
	            			 x = chatDisplayArea.getSelectionEnd();
	            			 chatDisplayArea.select(x,x);
	            			repaint();
	            			
	            			
	                		try {
								doc.insertString(endPoint, notification, keyWord);
								endPoint = endPoint + notification.length();
							} catch (BadLocationException e) {
								e.printStackTrace();
							}
	                		
	                	}
	                }
	            }).start();
		

	} 

	public String getNextMessage() { 
		String nextMessage = null; 
		while (nextMessage == null) { 
			try { 
				InputStream in = WebUtil.pullChatMessage();

				BufferedReader data = new BufferedReader(new InputStreamReader(in)); 
				nextMessage = data.readLine(); 
				System.out.println("Next Chat message: " + nextMessage);
				in.close();
				
			} catch (SocketException e) { 
				// Can't connect to host, report it and wait before trying again 
				System.out.println("Can't connect to host: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (FileNotFoundException e) { 
				// Servlet doesn't exist, report it and wait before trying again 
				System.out.println("Resource not found: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (Exception e) { // Some other problem, report it and wait before trying again 
				//ERIC COMMENTED OUT FOR DEBUGGING
				//System.out.println("General exception: " + e.getClass().getName() + ": " + e.getMessage()); 
				try { 
					Thread.sleep(1000); 
				} catch (InterruptedException ignored) { } } 
		} 
		
		return nextMessage + "\n"; 
	} 
	
	public String getNextSystemMessage() {
		String sysMess = null;
		while (sysMess == null) {
			try { 
				InputStream sysIn = WebUtil.pullSystemNote();

				
				BufferedReader data = new BufferedReader(new InputStreamReader(sysIn)); 
				sysMess = data.readLine(); 
				sysIn.close();
				
				
			} catch (SocketException e) { 
				// Can't connect to host, report it and wait before trying again 
				System.out.println("Can't connect to host: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (FileNotFoundException e) { 
				// Servlet doesn't exist, report it and wait before trying again 
				System.out.println("Resource not found: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (Exception e) { // Some other problem, report it and wait before trying again 
				//ERIC COMMENTED OUT FOR DEBUGGING
				//System.out.println("General exception: " + e.getClass().getName() + ": " + e.getMessage()); 
				try { 
					Thread.sleep(1000); 
				} catch (InterruptedException ignored) { } } 
		} 
		
		return sysMess;
	}
	
	public String getNextNotification() { 
		String highlightNotification = null;
		long notificationID = -1;
		while (highlightNotification == null) {
			try { 
				InputStream hilightIn = WebUtil.pullHighlightNotification();

				StringWriter writer = new StringWriter();
				IOUtils.copy(hilightIn, writer); 
				String networkString = writer.toString();
				
				System.out.println("NETWORK STRING : " + networkString);
				
				Properties props = PostIt.toProperties(networkString);
				
				String docName = PostItNetworking.getDocName(props);
				System.out.println("DOCNAME : " + networkString);
				
				notificationID = PostItNetworking.getSid(props);
				
				//CHECK ID to make sure its the same
				if(PostIt.getOwnerToken(props).equals(InfoViz.userToken)){
						if(!PostItNetworking.getMessage(props).equals("")){
							highlightNotification = "\n Your partner is interested in your Postit that contains the text \n\"" 
						+ PostItNetworking.getMessage(props) +
									"\"\n  Maybe you should talk about it. \n\n";
						}
				}
				
				System.out.println("1: " + highlightNotification);
				
				String h[] = highlightNotification.split("\\|");
				
				System.out.println("2: " + h[0]);
				System.out.println("3: " + h[1]);
				for(String s : h){
					s.replace(ESCAPE_STRING, "");
				}
				
				System.out.println(h[1] + " compare " + InfoViz.UserID);
				if(h[1].equals(InfoViz.UserID)){
					System.out.println("hilight data: " + highlightNotification);
					highlightNotification = null;
				}
				else{
					highlightNotification = h[0];
				}
				
				hilightIn.close();
			} catch (SocketException e) { 
				// Can't connect to host, report it and wait before trying again 
				System.out.println("Can't connect to host: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (FileNotFoundException e) { 
				// Servlet doesn't exist, report it and wait before trying again 
				System.out.println("Resource not found: " + e.getMessage()); 
				try { 
					Thread.sleep(5000); 
				} catch (InterruptedException ignored) { } 
			} catch (Exception e) { // Some other problem, report it and wait before trying again 
				//ERIC COMMENTED OUT FOR DEBUGGING
				//System.out.println("General exception: " + e.getClass().getName() + ": " + e.getMessage()); 
				try { 
					Thread.sleep(1000); 
				} catch (InterruptedException ignored) { } } 
		} 
			BoardPane.getInstance().postItFlash(notificationID);
			return highlightNotification;
	} 

	

	public void run() { 
		while (true) { 
			String fullMessage = getNextMessage();
			String token = fullMessage.substring(0, fullMessage.indexOf("|"));
			String username = fullMessage.substring(fullMessage.indexOf("|") + 1, fullMessage.indexOf(":"));
			String output = fullMessage.substring(fullMessage.indexOf(":"));
			
			
			Document doc = chatDisplayArea.getDocument();
    		SimpleAttributeSet keyWord = new SimpleAttributeSet();
    		
    			StyleConstants.setBold(keyWord, true);
    			
    		if(username.equals("Pat")){
    			StyleConstants.setForeground(keyWord, new Color(0xFF8300));
    		}
    		else{
    			StyleConstants.setForeground(keyWord, new Color(0xE8E800));
    		}
    		
    			StyleConstants.setFontSize(keyWord, 20);
    		
			
    		try {
    			doc.insertString(endPoint, "\u25CF", keyWord);
    			endPoint++;
    			
    			keyWord = new SimpleAttributeSet();
				StyleConstants.setFontSize(keyWord, 14);
				
				doc.insertString(endPoint, username, keyWord);
				endPoint = endPoint + username.length();
				
				
				doc.insertString(endPoint, output, keyWord);
				endPoint = endPoint + output.length();
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
			    
    		AudioClip ac = InfoViz.newAudioClip(Util.getServerResource("resources/audio/drip.au"));
    		ac.play(); 
    		try{
    			Thread.sleep(300);
    		}
    		catch(Exception e){
    			
    		}
    		ac.stop();
    		
    		UserLogWriter.addToChatLog(username, output.substring(2), FilenameUtils.getBaseName(AllComponents.getCurrentPath()));
    		
			//chatDisplayArea.append(output);
			int x;
			chatDisplayArea.selectAll();
			 x = chatDisplayArea.getSelectionEnd();
			 chatDisplayArea.select(x,x);
			repaint();
		} 
	} 

		
	// Sends out message to the other people. 
	void broadcastMessage(String message) { 
		message = InfoViz.userToken + "|" + user + ": " + message; 
		// Pre-pend the speaker's name 
		try { 
			WebUtil.sendChatMessage(message);			 
		} catch (SocketException e) { 
			// Can't connect to host, report it and abandon the broadcast 
			System.out.println("Can't connect to host: " + e.getMessage()); 
		} catch (FileNotFoundException e) { 
			// Servlet doesn't exist, report it and abandon the broadcast 
			System.out.println("Resource not found: " + e.getMessage()); 
		} catch (Exception e) { 
			// Some other problem, report it and abandon the broadcast 
			System.out.println("General exception: " + e.getClass().getName() + ": " + e.getMessage());
		} 
	} 
	
	public static void appendSysMessage(String notification){
		Document doc = chatDisplayArea.getDocument();
		
		SimpleAttributeSet keyWord = new SimpleAttributeSet();
		
		StyleConstants.setForeground(keyWord, Color.red);
		
		notification = "\n" + notification + "\n\n";
		
		int x;
		chatDisplayArea.selectAll();
		 x = chatDisplayArea.getSelectionEnd();
		 chatDisplayArea.select(x,x);
		
		
		try {
			doc.insertString(endPoint, notification, keyWord);
			endPoint = endPoint + notification.length();
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}
	
	

	private class TextHandler extends KeyAdapter {
		public void keyPressed(KeyEvent e) {
			String text = chatEntryArea.getText();
			if(e.getKeyCode() == 10 && !text.equals("")) {
				chatEntryArea.setText("");
				broadcastMessage(text);
			}
			
			
		}
	}
	
	public static HttpChatPanel getInstance(){
		return instance;
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		String mouseObject = "null";
		if(chatEntryArea.contains(arg0.getLocationOnScreen())){
			mouseObject = "Text Field";
		}
		
		System.out.println("hello");
		if(arg0.getClickCount() == 1){
			UserLogWriter.log2(Action.CLICK, "Chat", mouseObject, "null", "null", "null", "null", "null");
		}
		else{
			UserLogWriter.log2(Action.DOUBLECLICK, "Chat", mouseObject, "null", "null", "null", "null", "null");
		}
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
	}

	@Override
	public void mouseExited(MouseEvent arg0) {	
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		
	}

	@Override
	public void keyPressed(KeyEvent e) {
		
	}

	@Override
	public void keyReleased(KeyEvent e) {
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		
	}

	public void startListenerThread() {
		new Thread(
	            new Runnable() {
	                public void run() {
	                	while(true){
	                		if(instance.getBounds().contains(
	                				MouseInfo.getPointerInfo().getLocation().x, 
	                				MouseInfo.getPointerInfo().getLocation().y)){
	                			if(!mouseInside){
	                				System.out.println("mouse entered");	
		                		}
	                			mouseInside = true;
	                		}
	                		else{
	                			if(mouseInside){
		                			System.out.println("mouse left");
		                		}
	                			mouseInside = false;
	                		}
	                	}
	                }
	            }).start();
	}
	
	
}